using HtmlAgilityPack;
using Microsoft.EntityFrameworkCore;
using DaoHang.Data;
using DaoHang.Models;
using System.Text;
using System.Text.RegularExpressions;
using SkiaSharp;
using System.Threading;

namespace DaoHang.Services
{
    /// <summary>
    /// 图标服务实现
    /// 提供多种方法下载和管理网站图标
    /// </summary>
    public class IconService : IIconService
    {
        private readonly HttpClient httpClient;
        private readonly IWebHostEnvironment webHostEnvironment;
        private readonly ApplicationDbContext context;
        private readonly ILogger<IconService> logger;
        private readonly string iconsDirectory;
        private readonly string defaultIconFileName = "default-icon.png";

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="httpClient">HTTP客户端</param>
        /// <param name="webHostEnvironment">Web主机环境</param>
        /// <param name="context">数据库上下文</param>
        /// <param name="logger">日志记录器</param>
        public IconService(
            HttpClient httpClient,
            IWebHostEnvironment webHostEnvironment,
            ApplicationDbContext context,
            ILogger<IconService> logger)
        {
            this.httpClient = httpClient;
            this.webHostEnvironment = webHostEnvironment;
            this.context = context;
            this.logger = logger;
            
            // 设置图标存储目录
            iconsDirectory = Path.Combine(webHostEnvironment.WebRootPath, "icons");
            
            // 确保目录存在
            Directory.CreateDirectory(iconsDirectory);
            
            // 配置HttpClient
            httpClient.Timeout = TimeSpan.FromSeconds(30);
            httpClient.DefaultRequestHeaders.Add("User-Agent", 
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
        }

        /// <summary>
        /// 下载并保存网站图标到本地
        /// </summary>
        /// <param name="iconUrl">外部图标URL</param>
        /// <param name="websiteName">网站名称，用于生成文件名</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>本地图标相对路径，如果失败返回null</returns>
        public async Task<string?> DownloadAndSaveIconAsync(string iconUrl, string websiteName, CancellationToken cancellationToken = default)
        {
            if (string.IsNullOrEmpty(iconUrl) || string.IsNullOrEmpty(websiteName))
                return null;

            try
            {
                logger.LogInformation("开始下载图标: {IconUrl} for {WebsiteName}", iconUrl, websiteName);

                // 多次重试下载
                byte[]? iconData = await DownloadWithRetryAsync(iconUrl, 3, cancellationToken);
                if (iconData == null || cancellationToken.IsCancellationRequested)
                {
                    logger.LogWarning("下载图标失败: {IconUrl}", iconUrl);
                    return null;
                }

                // 验证图片数据
                if (!IsValidImageData(iconData))
                {
                    logger.LogWarning("下载的不是有效图片数据: {IconUrl}", iconUrl);
                    return null;
                }

                // 生成文件名
                string fileName = GenerateIconFileName(websiteName, iconUrl);
                string filePath = Path.Combine(iconsDirectory, fileName);

                // 保存文件
                await File.WriteAllBytesAsync(filePath, iconData, cancellationToken);
                
                logger.LogInformation("图标保存成功: {FileName} ({Size} bytes)", fileName, iconData.Length);
                
                return $"/icons/{fileName}";
            }
            catch (OperationCanceledException)
            {
                logger.LogDebug("下载图标操作被取消: {IconUrl}", iconUrl);
                return null;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "下载和保存图标时发生错误: {IconUrl}", iconUrl);
                return null;
            }
        }

        /// <summary>
        /// 向后兼容的下载方法（无CancellationToken）
        /// </summary>
        /// <param name="iconUrl">外部图标URL</param>
        /// <param name="websiteName">网站名称</param>
        /// <returns>本地图标相对路径</returns>
        public async Task<string?> DownloadAndSaveIconAsync(string iconUrl, string websiteName)
        {
            return await DownloadAndSaveIconAsync(iconUrl, websiteName, CancellationToken.None);
        }

        /// <summary>
        /// 从网站URL自动检测并下载图标 - 优化版本，支持并行处理
        /// </summary>
        /// <param name="websiteUrl">网站URL</param>
        /// <param name="websiteName">网站名称</param>
        /// <returns>本地图标相对路径，如果失败返回默认图标路径</returns>
        public async Task<string> DetectAndDownloadIconAsync(string websiteUrl, string websiteName)
        {
            logger.LogInformation("开始并行检测并下载图标: {WebsiteUrl} for {WebsiteName}", websiteUrl, websiteName);

            try
            {
                // 标准化URL
                if (!Uri.TryCreate(websiteUrl, UriKind.Absolute, out var uri))
                {
                    if (!websiteUrl.StartsWith("http://") && !websiteUrl.StartsWith("https://"))
                    {
                        websiteUrl = "https://" + websiteUrl;
                        if (!Uri.TryCreate(websiteUrl, UriKind.Absolute, out uri))
                        {
                            logger.LogWarning("无效的URL格式: {WebsiteUrl}", websiteUrl);
                            return GetDefaultIconPath();
                        }
                    }
                    else
                    {
                        logger.LogWarning("无效的URL格式: {WebsiteUrl}", websiteUrl);
                        return GetDefaultIconPath();
                    }
                }

                // 使用CancellationTokenSource来实现"一旦成功就取消其他任务"的逻辑
                using var cancellationTokenSource = new CancellationTokenSource();
                var cancellationToken = cancellationTokenSource.Token;

                // 创建所有下载任务
                var downloadTasks = new List<Task<string?>>();

                // 任务1: HTML解析图标链接
                downloadTasks.Add(TryDownloadFromHtmlAsync(uri, websiteName, cancellationToken));

                // 任务2-N: 标准路径尝试
                var standardPaths = GetStandardIconPaths(uri);
                foreach (var path in standardPaths.Take(5)) // 限制标准路径数量避免过多任务
                {
                    downloadTasks.Add(TryDownloadFromUrlAsync(path, websiteName, cancellationToken));
                }

                // 任务N+1-M: 第三方API服务
                var apiUrls = GetThirdPartyApiUrls(uri);
                foreach (var apiUrl in apiUrls.Take(3)) // 限制API服务数量避免过多请求
                {
                    downloadTasks.Add(TryDownloadFromUrlAsync(apiUrl, websiteName, cancellationToken));
                }

                logger.LogDebug("启动 {Count} 个并行下载任务", downloadTasks.Count);

                // 并行执行所有任务，只要有一个成功就返回
                while (downloadTasks.Any())
                {
                    try
                    {
                        var completedTask = await Task.WhenAny(downloadTasks);
                        var result = await completedTask;

                        if (!string.IsNullOrEmpty(result))
                        {
                            // 成功获取图标，取消其他所有任务
                            cancellationTokenSource.Cancel();
                            logger.LogInformation("并行下载成功，图标路径: {IconPath}", result);
                            return result;
                        }

                        // 当前任务失败，从列表中移除，继续等待其他任务
                        downloadTasks.Remove(completedTask);
                    }
                    catch (Exception ex)
                    {
                        logger.LogDebug(ex, "某个并行下载任务失败");
                        // 继续执行其他任务
                    }
                }

                logger.LogWarning("所有并行下载方法都失败，使用默认图标: {WebsiteUrl}", websiteUrl);
                return GetDefaultIconPath();
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "并行检测和下载图标时发生错误: {WebsiteUrl}", websiteUrl);
                return GetDefaultIconPath();
            }
        }

        /// <summary>
        /// 尝试从HTML页面下载图标的并行任务
        /// </summary>
        /// <param name="uri">网站URI</param>
        /// <param name="websiteName">网站名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>本地图标路径或null</returns>
        private async Task<string?> TryDownloadFromHtmlAsync(Uri uri, string websiteName, CancellationToken cancellationToken)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                    return null;

                logger.LogDebug("HTML解析任务开始: {Uri}", uri);
                var iconUrl = await ExtractIconFromHtmlAsync(uri, cancellationToken);
                
                if (cancellationToken.IsCancellationRequested)
                    return null;

                if (!string.IsNullOrEmpty(iconUrl))
                {
                    var result = await DownloadAndSaveIconAsync(iconUrl, websiteName, cancellationToken);
                    if (!string.IsNullOrEmpty(result))
                    {
                        logger.LogInformation("HTML解析任务成功: {IconUrl}", iconUrl);
                        return result;
                    }
                }
                
                return null;
            }
            catch (OperationCanceledException)
            {
                logger.LogDebug("HTML解析任务被取消");
                return null;
            }
            catch (Exception ex)
            {
                logger.LogDebug(ex, "HTML解析任务失败: {Uri}", uri);
                return null;
            }
        }

        /// <summary>
        /// 尝试从指定URL下载图标的并行任务
        /// </summary>
        /// <param name="iconUrl">图标URL</param>
        /// <param name="websiteName">网站名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>本地图标路径或null</returns>
        private async Task<string?> TryDownloadFromUrlAsync(string iconUrl, string websiteName, CancellationToken cancellationToken)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                    return null;

                logger.LogDebug("URL下载任务开始: {IconUrl}", iconUrl);
                var result = await DownloadAndSaveIconAsync(iconUrl, websiteName, cancellationToken);
                
                if (!string.IsNullOrEmpty(result))
                {
                    logger.LogInformation("URL下载任务成功: {IconUrl}", iconUrl);
                    return result;
                }
                
                return null;
            }
            catch (OperationCanceledException)
            {
                logger.LogDebug("URL下载任务被取消: {IconUrl}", iconUrl);
                return null;
            }
            catch (Exception ex)
            {
                logger.LogDebug(ex, "URL下载任务失败: {IconUrl}", iconUrl);
                return null;
            }
        }

        /// <summary>
        /// 从HTML页面解析图标链接
        /// </summary>
        /// <param name="uri">网站URI</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>图标URL</returns>
        private async Task<string?> ExtractIconFromHtmlAsync(Uri uri, CancellationToken cancellationToken = default)
        {
            try
            {
                logger.LogDebug("开始从HTML解析图标: {Uri}", uri);

                var response = await httpClient.GetAsync(uri, cancellationToken);
                if (!response.IsSuccessStatusCode)
                {
                    logger.LogWarning("HTML页面请求失败: {StatusCode} for {Uri}", response.StatusCode, uri);
                    return null;
                }

                var html = await response.Content.ReadAsStringAsync(cancellationToken);
                
                if (cancellationToken.IsCancellationRequested)
                    return null;
                
                var doc = new HtmlDocument();
                doc.LoadHtml(html);

                // 优先级排序的选择器
                var selectors = new[]
                {
                    "//link[@rel='icon' and @type='image/png']",
                    "//link[@rel='icon' and @type='image/x-icon']", 
                    "//link[@rel='shortcut icon']",
                    "//link[@rel='apple-touch-icon']",
                    "//link[@rel='apple-touch-icon-precomposed']",
                    "//link[contains(@rel, 'icon')]",
                    "//meta[@property='og:image']"
                };

                foreach (var selector in selectors)
                {
                    if (cancellationToken.IsCancellationRequested)
                        return null;
                        
                    var nodes = doc.DocumentNode.SelectNodes(selector);
                    if (nodes != null)
                    {
                        foreach (var node in nodes)
                        {
                            var href = node.GetAttributeValue("href", "") ?? 
                                      node.GetAttributeValue("content", "");
                            
                            if (!string.IsNullOrEmpty(href))
                            {
                                var fullUrl = GetAbsoluteUrl(uri, href);
                                if (!string.IsNullOrEmpty(fullUrl))
                                {
                                    logger.LogDebug("从HTML解析到图标URL: {IconUrl}", fullUrl);
                                    return fullUrl;
                                }
                            }
                        }
                    }
                }

                logger.LogDebug("HTML中未找到图标链接: {Uri}", uri);
                return null;
            }
            catch (OperationCanceledException)
            {
                logger.LogDebug("HTML解析操作被取消: {Uri}", uri);
                return null;
            }
            catch (Exception ex)
            {
                logger.LogWarning(ex, "从HTML解析图标时发生错误: {Uri}", uri);
                return null;
            }
        }

        /// <summary>
        /// 向后兼容的HTML解析方法（无CancellationToken）
        /// </summary>
        /// <param name="uri">网站URI</param>
        /// <returns>图标URL</returns>
        private async Task<string?> ExtractIconFromHtmlAsync(Uri uri)
        {
            return await ExtractIconFromHtmlAsync(uri, CancellationToken.None);
        }

        /// <summary>
        /// 获取标准图标路径
        /// </summary>
        /// <param name="uri">网站URI</param>
        /// <returns>标准图标路径列表</returns>
        private List<string> GetStandardIconPaths(Uri uri)
        {
            var baseUrl = $"{uri.Scheme}://{uri.Host}";
            
            return new List<string>
            {
                $"{baseUrl}/favicon.ico",
                $"{baseUrl}/favicon.png",
                $"{baseUrl}/apple-touch-icon.png",
                $"{baseUrl}/apple-touch-icon-precomposed.png",
                $"{baseUrl}/apple-touch-icon-180x180.png",
                $"{baseUrl}/apple-touch-icon-152x152.png",
                $"{baseUrl}/apple-touch-icon-144x144.png",
                $"{baseUrl}/apple-touch-icon-120x120.png",
                $"{baseUrl}/apple-touch-icon-76x76.png",
                $"{baseUrl}/apple-touch-icon-60x60.png",
                $"{baseUrl}/apple-touch-icon-57x57.png",
                $"{baseUrl}/assets/favicon.ico",
                $"{baseUrl}/static/favicon.ico",
                $"{baseUrl}/img/favicon.ico",
                $"{baseUrl}/images/favicon.ico"
            };
        }

        /// <summary>
        /// 获取第三方API服务URL
        /// </summary>
        /// <param name="uri">网站URI</param>
        /// <returns>第三方API URL列表</returns>
        private List<string> GetThirdPartyApiUrls(Uri uri)
        {
            var domain = uri.Host;
            
            return new List<string>
            {
                $"https://www.google.com/s2/favicons?domain={domain}&sz=32",
                $"https://www.google.com/s2/favicons?domain={domain}&sz=64",
                $"https://favicons.githubusercontent.com/{domain}",
                $"https://icon.horse/icon/{domain}",
                $"https://www.faviconextractor.com/favicon/{domain}",
                $"https://api.faviconkit.com/{domain}/64"
            };
        }

        /// <summary>
        /// 带重试的下载方法
        /// </summary>
        /// <param name="url">下载URL</param>
        /// <param name="maxRetries">最大重试次数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>下载的数据</returns>
        private async Task<byte[]?> DownloadWithRetryAsync(string url, int maxRetries, CancellationToken cancellationToken = default)
        {
            for (int i = 0; i <= maxRetries; i++)
            {
                try
                {
                    if (cancellationToken.IsCancellationRequested)
                        return null;
                        
                    logger.LogDebug("尝试下载 (第{Attempt}次): {Url}", i + 1, url);
                    
                    var response = await httpClient.GetAsync(url, cancellationToken);
                    if (response.IsSuccessStatusCode)
                    {
                        var data = await response.Content.ReadAsByteArrayAsync(cancellationToken);
                        if (data.Length > 0)
                        {
                            logger.LogDebug("下载成功: {Url} ({Size} bytes)", url, data.Length);
                            return data;
                        }
                    }
                    
                    logger.LogDebug("下载失败: {StatusCode} for {Url}", response.StatusCode, url);
                }
                catch (OperationCanceledException)
                {
                    logger.LogDebug("下载操作被取消: {Url}", url);
                    return null;
                }
                catch (Exception ex)
                {
                    logger.LogDebug(ex, "下载异常 (第{Attempt}次): {Url}", i + 1, url);
                }

                // 如果不是最后一次尝试，则等待后重试
                if (i < maxRetries && !cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        await Task.Delay(1000 * (i + 1), cancellationToken); // 递增延迟
                    }
                    catch (OperationCanceledException)
                    {
                        logger.LogDebug("重试延迟被取消: {Url}", url);
                        return null;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// 向后兼容的下载方法（无CancellationToken）
        /// </summary>
        /// <param name="url">下载URL</param>
        /// <param name="maxRetries">最大重试次数</param>
        /// <returns>下载的数据</returns>
        private async Task<byte[]?> DownloadWithRetryAsync(string url, int maxRetries)
        {
            return await DownloadWithRetryAsync(url, maxRetries, CancellationToken.None);
        }

        /// <summary>
        /// 验证是否为有效图片数据
        /// </summary>
        /// <param name="data">图片数据</param>
        /// <returns>是否有效</returns>
        private bool IsValidImageData(byte[] data)
        {
            if (data == null || data.Length < 10)
                return false;

            try
            {
                // 检查常见图片格式的文件头
                var header = data.Take(10).ToArray();
                
                // PNG: 89 50 4E 47 0D 0A 1A 0A
                if (header.Length >= 8 && 
                    header[0] == 0x89 && header[1] == 0x50 && 
                    header[2] == 0x4E && header[3] == 0x47)
                    return true;

                // JPEG: FF D8 FF
                if (header.Length >= 3 && 
                    header[0] == 0xFF && header[1] == 0xD8 && header[2] == 0xFF)
                    return true;

                // GIF: 47 49 46 38
                if (header.Length >= 4 && 
                    header[0] == 0x47 && header[1] == 0x49 && 
                    header[2] == 0x46 && header[3] == 0x38)
                    return true;

                // ICO: 00 00 01 00
                if (header.Length >= 4 && 
                    header[0] == 0x00 && header[1] == 0x00 && 
                    header[2] == 0x01 && header[3] == 0x00)
                    return true;

                // WebP: 52 49 46 46 ... 57 45 42 50
                if (header.Length >= 4 && 
                    header[0] == 0x52 && header[1] == 0x49 && 
                    header[2] == 0x46 && header[3] == 0x46)
                    return true;

                return false;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 生成图标文件名
        /// </summary>
        /// <param name="websiteName">网站名称</param>
        /// <param name="iconUrl">图标URL</param>
        /// <returns>文件名</returns>
        private string GenerateIconFileName(string websiteName, string iconUrl)
        {
            // 清理网站名称
            var cleanName = CleanFileName(websiteName);
            
            // 从URL获取文件扩展名
            var extension = GetFileExtension(iconUrl);
            
            // 生成唯一标识符
            var hash = GetHashString(iconUrl);
            
            return $"{cleanName}_{hash}{extension}";
        }

        /// <summary>
        /// 清理文件名
        /// </summary>
        /// <param name="fileName">原始文件名</param>
        /// <returns>清理后的文件名</returns>
        private string CleanFileName(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
                return "unknown";

            // 移除无效字符
            var invalidChars = Path.GetInvalidFileNameChars();
            var cleanName = string.Join("_", fileName.Split(invalidChars, StringSplitOptions.RemoveEmptyEntries));
            
            // 限制长度
            if (cleanName.Length > 50)
                cleanName = cleanName.Substring(0, 50);
                
            // 移除特殊字符，只保留字母数字和下划线
            cleanName = Regex.Replace(cleanName, @"[^\w\u4e00-\u9fa5_-]", "_");
            
            return string.IsNullOrEmpty(cleanName) ? "unknown" : cleanName.ToLower();
        }

        /// <summary>
        /// 获取文件扩展名
        /// </summary>
        /// <param name="url">URL</param>
        /// <returns>扩展名</returns>
        private string GetFileExtension(string url)
        {
            try
            {
                var uri = new Uri(url);
                var path = uri.AbsolutePath;
                var extension = Path.GetExtension(path);
                
                if (string.IsNullOrEmpty(extension))
                    return ".png"; // 默认扩展名
                    
                return extension.ToLower();
            }
            catch
            {
                return ".png";
            }
        }

        /// <summary>
        /// 获取字符串哈希值
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>哈希值</returns>
        private string GetHashString(string input)
        {
            var bytes = Encoding.UTF8.GetBytes(input);
            var hash = System.Security.Cryptography.MD5.HashData(bytes);
            return Convert.ToHexString(hash)[..8].ToLower();
        }

        /// <summary>
        /// 获取绝对URL
        /// </summary>
        /// <param name="baseUri">基础URI</param>
        /// <param name="relativeUrl">相对URL</param>
        /// <returns>绝对URL</returns>
        private string? GetAbsoluteUrl(Uri baseUri, string relativeUrl)
        {
            try
            {
                if (string.IsNullOrEmpty(relativeUrl))
                    return null;

                // 如果已经是绝对URL
                if (Uri.IsWellFormedUriString(relativeUrl, UriKind.Absolute))
                    return relativeUrl;

                // 协议相对URL
                if (relativeUrl.StartsWith("//"))
                    return baseUri.Scheme + ":" + relativeUrl;

                // 相对URL
                var uri = new Uri(baseUri, relativeUrl);
                return uri.ToString();
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 批量更新网站图标 - 优化版本，支持并行处理
        /// </summary>
        /// <returns>更新结果</returns>
        public async Task<IconUpdateResult> BatchUpdateIconsAsync()
        {
            logger.LogInformation("开始并行批量更新网站图标");

            var result = new IconUpdateResult();
            
            try
            {
                var websites = await context.Websites.ToListAsync();
                result.TotalCount = websites.Count;

                if (websites.Count == 0)
                {
                    logger.LogInformation("没有网站需要更新图标");
                    return result;
                }

                // 设置并发度，避免过多并发请求
                var maxConcurrency = Math.Min(Environment.ProcessorCount * 2, 10);
                var semaphore = new SemaphoreSlim(maxConcurrency, maxConcurrency);
                
                logger.LogInformation("使用并发度: {MaxConcurrency}，处理 {TotalCount} 个网站", maxConcurrency, websites.Count);

                // 创建所有网站的更新任务
                var updateTasks = websites.Select(async website =>
                {
                    await semaphore.WaitAsync();
                    try
                    {
                        return await UpdateSingleWebsiteIconAsync(website);
                    }
                    finally
                    {
                        semaphore.Release();
                    }
                }).ToList();

                // 并行执行所有更新任务
                var updateResults = await Task.WhenAll(updateTasks);

                // 汇总结果
                foreach (var updateResult in updateResults)
                {
                    switch (updateResult.Status)
                    {
                        case IconUpdateStatus.Success:
                            result.SuccessCount++;
                            break;
                        case IconUpdateStatus.Failed:
                            result.FailureCount++;
                            if (!string.IsNullOrEmpty(updateResult.ErrorMessage))
                                result.ErrorMessages.Add(updateResult.ErrorMessage);
                            break;
                        case IconUpdateStatus.DefaultIcon:
                            result.DefaultIconCount++;
                            break;
                    }
                }

                // 批量保存数据库更改
                await context.SaveChangesAsync();
                
                logger.LogInformation("并行批量更新完成: 总数={Total}, 成功={Success}, 失败={Failure}, 默认图标={Default}", 
                    result.TotalCount, result.SuccessCount, result.FailureCount, result.DefaultIconCount);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "并行批量更新图标时发生错误");
                result.ErrorMessages.Add($"并行批量更新时发生错误: {ex.Message}");
            }

            return result;
        }

        /// <summary>
        /// 更新单个网站图标的任务
        /// </summary>
        /// <param name="website">网站对象</param>
        /// <returns>更新结果</returns>
        private async Task<SingleIconUpdateResult> UpdateSingleWebsiteIconAsync(Website website)
        {
            try
            {
                logger.LogDebug("开始更新网站图标: {WebsiteName} ({WebsiteUrl})", website.Name, website.Url);

                var iconPath = await DetectAndDownloadIconAsync(website.Url, website.Name);
                
                if (iconPath == GetDefaultIconPath())
                {
                    logger.LogWarning("网站使用默认图标: {WebsiteName}", website.Name);
                    website.IconUrl = iconPath;
                    context.Websites.Update(website);
                    return new SingleIconUpdateResult 
                    { 
                        Status = IconUpdateStatus.DefaultIcon,
                        WebsiteName = website.Name
                    };
                }
                else
                {
                    logger.LogInformation("网站图标更新成功: {WebsiteName} -> {IconPath}", website.Name, iconPath);
                    website.IconUrl = iconPath;
                    context.Websites.Update(website);
                    return new SingleIconUpdateResult 
                    { 
                        Status = IconUpdateStatus.Success,
                        WebsiteName = website.Name,
                        IconPath = iconPath
                    };
                }
            }
            catch (Exception ex)
            {
                var errorMsg = $"更新 {website.Name} 图标失败: {ex.Message}";
                logger.LogError(ex, "更新网站图标失败: {WebsiteName}", website.Name);
                
                // 设置为默认图标
                website.IconUrl = GetDefaultIconPath();
                context.Websites.Update(website);
                
                return new SingleIconUpdateResult 
                { 
                    Status = IconUpdateStatus.Failed,
                    WebsiteName = website.Name,
                    ErrorMessage = errorMsg
                };
            }
        }

        /// <summary>
        /// 单个图标更新结果
        /// </summary>
        private class SingleIconUpdateResult
        {
            public IconUpdateStatus Status { get; set; }
            public string WebsiteName { get; set; } = string.Empty;
            public string? IconPath { get; set; }
            public string? ErrorMessage { get; set; }
        }

        /// <summary>
        /// 图标更新状态枚举
        /// </summary>
        private enum IconUpdateStatus
        {
            Success,
            Failed,
            DefaultIcon
        }

        /// <summary>
        /// 获取默认图标路径
        /// </summary>
        /// <returns>默认图标的相对路径</returns>
        public string GetDefaultIconPath()
        {
            return $"/icons/{defaultIconFileName}";
        }

        /// <summary>
        /// 清理未使用的图标文件
        /// </summary>
        /// <returns>清理的文件数量</returns>
        public async Task<int> CleanupUnusedIconsAsync()
        {
            logger.LogInformation("开始清理未使用的图标文件");

            try
            {
                if (!Directory.Exists(iconsDirectory))
                    return 0;

                // 获取数据库中使用的图标路径
                var usedIcons = await context.Websites
                    .Where(w => !string.IsNullOrEmpty(w.IconUrl) && w.IconUrl.StartsWith("/icons/"))
                    .Select(w => w.IconUrl)
                    .ToListAsync();

                var usedFileNames = usedIcons
                    .Select(path => Path.GetFileName(path.Replace("/icons/", "")))
                    .Where(name => !string.IsNullOrEmpty(name))
                    .ToHashSet();

                // 添加默认图标到保护列表
                usedFileNames.Add(defaultIconFileName);

                // 获取目录中的所有文件
                var allFiles = Directory.GetFiles(iconsDirectory);
                int deletedCount = 0;

                foreach (var filePath in allFiles)
                {
                    var fileName = Path.GetFileName(filePath);
                    if (!usedFileNames.Contains(fileName))
                    {
                        try
                        {
                            File.Delete(filePath);
                            deletedCount++;
                            logger.LogDebug("删除未使用的图标文件: {FileName}", fileName);
                        }
                        catch (Exception ex)
                        {
                            logger.LogWarning(ex, "删除文件失败: {FilePath}", filePath);
                        }
                    }
                }

                logger.LogInformation("清理完成，删除了 {Count} 个未使用的图标文件", deletedCount);
                return deletedCount;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "清理图标文件时发生错误");
                return 0;
            }
        }

        /// <summary>
        /// 检查图标文件是否存在
        /// </summary>
        /// <param name="iconPath">图标相对路径</param>
        /// <returns>文件是否存在</returns>
        public bool IconExists(string iconPath)
        {
            if (string.IsNullOrEmpty(iconPath))
                return false;

            try
            {
                var fileName = iconPath.Replace("/icons/", "");
                var filePath = Path.Combine(iconsDirectory, fileName);
                return File.Exists(filePath);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 生成默认图标文件
        /// </summary>
        /// <returns>默认图标路径</returns>
        public async Task<string> GenerateDefaultIconAsync()
        {
            var defaultIconPath = Path.Combine(iconsDirectory, defaultIconFileName);
            
            if (File.Exists(defaultIconPath))
            {
                logger.LogDebug("默认图标文件已存在: {Path}", defaultIconPath);
                return GetDefaultIconPath();
            }

            try
            {
                logger.LogInformation("生成默认图标文件: {Path}", defaultIconPath);

                // 使用SkiaSharp创建一个跨平台的32x32默认图标
                using var surface = SKSurface.Create(new SKImageInfo(32, 32));
                var canvas = surface.Canvas;
                
                // 清除画布并填充背景色（主题色）
                canvas.Clear(new SKColor(102, 126, 234));
                
                // 创建画笔
                using var paint = new SKPaint
                {
                    Color = SKColors.White,
                    StrokeWidth = 2,
                    Style = SKPaintStyle.Stroke,
                    IsAntialias = true
                };
                
                // 绘制地球图标
                canvas.DrawCircle(16, 16, 12, paint);
                canvas.DrawLine(16, 4, 16, 28, paint);
                canvas.DrawLine(4, 16, 28, 16, paint);
                
                // 保存为PNG
                using var image = surface.Snapshot();
                using var data = image.Encode(SKEncodedImageFormat.Png, 100);
                await File.WriteAllBytesAsync(defaultIconPath, data.ToArray());
                
                logger.LogInformation("默认图标生成成功: {Path}", defaultIconPath);
                return GetDefaultIconPath();
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "生成默认图标失败");
                
                // 如果生成失败，创建一个最小的透明PNG
                var transparentPng = Convert.FromBase64String(
                    "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAdgAAAHYBTnsmCAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABYSURBVBiVY2RgYPjPQAYwirkzMzGQDVhAUf/BwPAfm2JsBqCLD5AcHCBFB7AZgE0xNgPQxQdIDg6QogPYDMCmGJsB6OIDJAcHSNEBbAZgU4zNAHTxAZKDA6QAAIJGBgzBSEpCAAAAAElFTkSuQmCC");
                
                await File.WriteAllBytesAsync(defaultIconPath, transparentPng);
                return GetDefaultIconPath();
            }
        }
    }
} 